/*
    $Header: /Windows/Shell/ShellExt.root/ShellExt/src/CCpHook.cpp 1     08-01-05 0:08 Ken $
    $Log: /Windows/Shell/ShellExt.root/ShellExt/src/CCpHook.cpp $
 * 
 * 1     08-01-05 0:08 Ken
*/


#include "stdafx.h"

// CCpHook
#include "CCpHook.h"
#include "CJunction.h"
#include "CStream.h"
#include "CShellExtXML.h"
#include "Misc.h"

//register junction do xml call back
//static CJunctDoXMLCb s_junctDoXMLCb;

UINT CCpHook::CopyCallback( HWND hwnd,UINT wFunc, UINT wFlags, LPCTSTR pszSrcFile,
      DWORD dwSrcAttribs, LPCTSTR pszDestFile, DWORD dwDestAttribs)
{
    TCHAR szJunctTgt[MAX_PATH];
    if(FALSE==CJunction::IsJunction(pszSrcFile, szJunctTgt, ARRAYOF(szJunctTgt)))
    {
        return IDYES;
    }

    UINT ret;

    switch (wFunc)
    {
    case FO_COPY:
        ret=DoFO_COPY(szJunctTgt, pszDestFile, hwnd);
        break;

        // pszDestFile=NULL
    case FO_DELETE:
        ret=DoFO_DELETE(pszSrcFile, hwnd);
        break;

    case FO_MOVE:
        if(pszSrcFile[0]==pszDestFile[0] &&
            //  move in the same volume
            _T(':')==pszSrcFile[1] && _T(':')==pszDestFile[1] &&
            _T('\\')==pszSrcFile[2] && _T('\\')==pszDestFile[2] )
        {
            ret=IDYES;
            break;
        }
        else
        {
            // move in different volume
            if( (IDNO!=DoFO_COPY(szJunctTgt, pszDestFile, hwnd))
                ||(IDNO!=DoFO_DELETE(pszSrcFile,  hwnd)))
            {
                ret=IDCANCEL;
                break;
            }
        }
        ret=IDNO;
    break;

    case FO_RENAME:
        ret=IDYES;
        break;

    default:
        ATLTRACE(_T("CopyCallback type:%d src:%s, des:%s\r\n"), wFunc, pszSrcFile, pszDestFile);
        ret=IDYES;
        break;
    }

    return ret;
}

UINT CCpHook::DoFO_COPY(LPCTSTR pszJunctTgt, LPCTSTR pszDestFile, HWND hwnd)
{
    int iRet;
    BOOL fCreateJunctForce=FALSE;
    TCHAR szInfo[512];
    UINT uDoSilence;

    if(PathFileExists(pszDestFile))
    {
        ATLTRACE(_T("FO_COPY src:%s, des:%s is the same!\r\n"), pszJunctTgt, pszDestFile);
        uDoSilence=DoSilenceOpt(CPHK_DOSILENCE_CAUSE_PATH, hwnd);
        if(0==uDoSilence)
        {
            _stprintf_s(szInfo, _T("Dir:%s had already exist!\r\nCopy junction here will lose all data in this dir\r\nDo you want continue?\r\n\r\nPress shift to make as default select!"), pszDestFile);
            iRet=MessageBox(NULL, szInfo, _T("Copy junction Warnning!"), MB_YESNOCANCEL);
            // ignore all PathFileExists
            if( (0x8000&GetAsyncKeyState(VK_SHIFT))!=0)
            {
                m_enDoSilence[CPHK_DOSILENCE_CAUSE_PATH]=iRet;
                m_hwnd=hwnd;
            }
            if(IDYES!=iRet)
            {
                return iRet;
            }
        }
        else if(IDYES!=uDoSilence)
        {
            return uDoSilence;
        }

        fCreateJunctForce=TRUE;
    }

    if(FALSE==CJunction::CreateJunction(pszDestFile, pszJunctTgt, fCreateJunctForce))
    {
        ATLTRACE(_T("Can't copy junction:%s here:%s!\r\n"), pszJunctTgt, pszDestFile);

        // store junction info for restore
        CShellExtXML cshlextXML;
        TCHAR szXMLFile[]=_T("A:\\ShellExt.xml");
        szXMLFile[0]=pszDestFile[0];
        if(FALSE!=cshlextXML.Init(szXMLFile, TRUE))
        {
            VOID* Hnd=cshlextXML.BgnSetCmdInfo(_T("Junction"));
            if(NULL!=Hnd)
            {
                cshlextXML.SetCmdInfo(Hnd, _T("JunctPath"), _variant_t(pszDestFile));
                cshlextXML.SetCmdInfo(Hnd, _T("JunctTarget"), _variant_t(pszJunctTgt));
                cshlextXML.EndSetCmdInfo(Hnd);
            }
        }

        uDoSilence=DoSilenceOpt(CPHK_DOSILENCE_CAUSE_CREATE, hwnd);
        if(0==uDoSilence)
        {
            _stprintf_s(szInfo, ARRAYOF(szInfo), _T("Can't copy junction:%s here:%s!\r\nDo you want continue?\r\n\r\nPress shift to make as default select!\r\n"), pszJunctTgt, pszDestFile);
            iRet=MessageBox(NULL, szInfo, _T("Copy junction Warnning!"), MB_YESNO);
            // ignore all CreateJunction faild
            if( (0x8000&GetAsyncKeyState(VK_SHIFT))!=0)
            {
                m_enDoSilence[CPHK_DOSILENCE_CAUSE_CREATE]=iRet;
                m_hwnd=hwnd;
            }

            if(IDNO==iRet)
            {
                return IDCANCEL;
            }
        }
        else if(IDNO==uDoSilence)
        {
            return IDCANCEL;
        }
    }

    return IDNO;    // we had do the copy, so explorer no need to da again
}

UINT CCpHook::DoFO_DELETE(LPCTSTR pszJunctName, HWND hwnd)
{
    TCHAR szInfo[512];

    if(FALSE==CJunction::DelJunction(pszJunctName))
    {
        ATLTRACE(_T("FO_DELETE junction:%sfaild!\r\n"), pszJunctName);
        UINT uDoSilence=DoSilenceOpt(CPHK_DOSILENCE_CAUSE_DEL, hwnd);
        if(0==uDoSilence)
        {
            _stprintf_s(szInfo, ARRAYOF(szInfo), _T("Can't delete junction:%s!\r\nDo you want continue?\r\n\r\nPress shift to make as default select!"), pszJunctName);
            int iRet=MessageBox(NULL, szInfo, _T("Delete junction error!"), MB_YESNO);

        // ignore all DelJunction faild
            if( (0x8000&GetAsyncKeyState(VK_SHIFT))!=0)
            {
                m_enDoSilence[CPHK_DOSILENCE_CAUSE_DEL]=iRet;
                m_hwnd=hwnd;
            }

            if(IDNO==iRet)
            {
                return IDCANCEL;
            }
        }
    }

    return IDNO;    // we had do the copy, so explorer no need to da again
}

UINT CCpHook::DoSilenceOpt(EN_CPHK_DOSELENCE_CAUSE enCause, HWND hwnd)
{
    if(hwnd==m_hwnd)
    {
        return m_enDoSilence[enCause];
    }

    memset(m_enDoSilence, 0, sizeof(m_enDoSilence));
    return 0;
}


